﻿#include "IOCPAppImpl.h"
#include <tchar.h>
#include <stdio.h>

#define  TCP_APP_PROXY_DEFAULT_IP   "127.0.0.1"
#define  TCP_APP_PROXY_DEFAULT_PORT  4435

CIOCPAppSrvBase::CIOCPAppSrvBase(LPCSTR lpAddress, int nPort) :
    m_pIOCPSrvImpl(new CIOCPServerModel(lpAddress, nPort, this))
{
}

CIOCPAppSrvBase::~CIOCPAppSrvBase()
{
    if (m_pIOCPSrvImpl)
    {
        m_pIOCPSrvImpl->Stop();
    }
    SAFEDELEPTR(m_pIOCPSrvImpl);
}

BOOL CIOCPAppSrvBase::StartServer()
{
    BOOL bRet = FALSE;
    do
    {
        if (!m_pIOCPSrvImpl)
            break;
        if (!m_pIOCPSrvImpl->GetIOCPServerCallBackPtr())
        {
            m_pIOCPSrvImpl->SetIOCPServerCallBackPtr(this);
        }
        bRet = m_pIOCPSrvImpl->Start();
        OnOutPutMsg(L"[IOCP] started, AppType:%s", GetIOCPAppTypeStr());
    } while (FALSE);
    return bRet;
}

BOOL CIOCPAppSrvBase::StopServer()
{
    do
    {
        if (!m_pIOCPSrvImpl)
            break;
        return m_pIOCPSrvImpl->Stop();
    } while (FALSE);
    return FALSE;
}

BOOL CIOCPAppSrvBase::DisconnectByIOCPAppType(EmIOCPAppType emType)
{
    BOOL bRet = FALSE;
    CIOCPAppSrvBase* p = GetHeadNode();
    for (; p != NULL; p = p->GetNextNode()) {
        if (emType == p->GetIOCPAppType()) {
            p->StopServer();
            bRet = TRUE;
        }
    }
    return bRet;
}

BOOL CIOCPAppSrvBase::SendDataByConnectID(UINT uiConID, LPCSTR lpData, ULONG ulDataSize)
{
    CIOCPAppSrvBase* p = GetHeadNode();
    for (; p != NULL; p = p->GetNextNode()) {
        if (p->m_pIOCPSrvImpl &&
            p->m_pIOCPSrvImpl->SendDataByConnectID(uiConID, lpData, ulDataSize)) {
            return TRUE;
        }
    }
    return FALSE;
}

// 新连接建立
void CIOCPAppSrvBase::OnConnectionEstablished(LPPER_SOCKET_CONTEXT pSocketContext)
{
    OnOutPutMsg(L"[IOCP] connection Established, connectID:%d, AppType:%s", pSocketContext ? pSocketContext->m_uiConnectID : 0, GetIOCPAppTypeStr());
}

// 连接关闭
void CIOCPAppSrvBase::OnConnectionClosed(LPPER_SOCKET_CONTEXT pSocketContext)
{
    OnOutPutMsg(L"[IOCP] connection closed, connectID:%d, AppType:%s", pSocketContext ? pSocketContext->m_uiConnectID : 0, GetIOCPAppTypeStr());
}

// 错误提示
void CIOCPAppSrvBase::OnOutPutMsg(const std::wstring strMsg, ...)
{
    // 处理变长参数
    va_list   arglist;
    va_start(arglist, strMsg);
    std::string strFormat = "%s-%d::";

    int iLen = _vsctprintf(strMsg.c_str(), arglist);
    wchar_t* pBuf = new wchar_t[iLen+2];
    int count = _vsnwprintf_s(pBuf, iLen + 1, _TRUNCATE, strMsg.c_str(), arglist);
    wprintf(pBuf);
    wprintf(L"\n");
    delete[] pBuf;
    va_end(arglist);
}

// 连接上发生错误
void CIOCPAppSrvBase::OnConnectionError(LPPER_SOCKET_CONTEXT pSocketContext, int error)
{
    OnOutPutMsg(L"[IOCP] connect catch error:%d, connectID:%d, AppType:%s", error,
        pSocketContext ? pSocketContext->m_uiConnectID : 0, GetIOCPAppTypeStr());
}

// 读操作完成
void CIOCPAppSrvBase::OnRecvCompleted(LPPER_SOCKET_CONTEXT pSocketContext, LPPER_IO_CONTEXT pIoContext, UINT uiBytesTrans)
{
    OnOutPutMsg(L"[IOCP] recv data completed, connectID:%d, AppType:%s, BytesTransfer:%d",
        pIoContext ? pIoContext->m_uiConnectID : 0, GetIOCPAppTypeStr(), uiBytesTrans);
}

// 写操作完成
void CIOCPAppSrvBase::OnSendCompleted(LPPER_SOCKET_CONTEXT pSocketContext, LPPER_IO_CONTEXT pIoContext, UINT uiBytesTrans)
{
    OnOutPutMsg(L"[IOCP] send data completed, connectID:%d, AppType:%s dataSize:%d",
        pIoContext ? pIoContext->m_uiConnectID : 0, GetIOCPAppTypeStr(), uiBytesTrans);
}

// iocp失败
void CIOCPAppSrvBase::OnIOCPCaughtError(INT iIOCPErr, INT iWSAErr)
{
    OnOutPutMsg(L"[IOCP] caught iocp error:%d, WSASocketError:%d, AppType:%s",
        iIOCPErr, iWSAErr, GetIOCPAppTypeStr());
    //g_errorno = iIOCPErr;
}

// IOCP初始化ok
void CIOCPAppSrvBase::OnIOCPInitializeFinished()
{
    //g_errorno = NET_OK;
}


/////////////////////////////////////////////////////////////////////////////
CAppIOCPSrvImpl::CAppIOCPSrvImpl() :
    CIOCPAppSrvBase(TCP_APP_PROXY_DEFAULT_IP, TCP_APP_PROXY_DEFAULT_PORT)
{
}

CAppIOCPSrvImpl::CAppIOCPSrvImpl(LPCSTR lpAddress, int nPort) :
    CIOCPAppSrvBase(lpAddress, nPort)
{
}

CAppIOCPSrvImpl::~CAppIOCPSrvImpl()
{
}

///< 获取应用类型
EmIOCPAppType CAppIOCPSrvImpl::GetIOCPAppType()
{
    return (EmIOCPAppType)CAppIOCPSrvImpl::GetRegType();
}

///< 获取应用Str类型
LPCWSTR CAppIOCPSrvImpl::GetIOCPAppTypeStr()
{
    return CAppIOCPSrvImpl::GetRegItemName();
}

// 连接上发生错误
void CAppIOCPSrvImpl::OnConnectionError(LPPER_SOCKET_CONTEXT pSocketContext, int error)
{
    CIOCPAppSrvBase::OnConnectionError(pSocketContext, error);  // print msg
}

// 读操作完成
void CAppIOCPSrvImpl::OnRecvCompleted(LPPER_SOCKET_CONTEXT pSocketContext, LPPER_IO_CONTEXT pIoContext, UINT uiBytesTrans)
{
    CIOCPAppSrvBase::OnRecvCompleted(pSocketContext, pIoContext, uiBytesTrans);
}

// socket 绑定端口失败
void CAppIOCPSrvImpl::OnIOCPCaughtError(INT iIOCPErr, INT iWSAErr)
{
    if (iIOCPErr == NET_IOCP_Bind)
    {   // 端口被占用了  启用端口转发 代理模式  445端口可能被其他进程占用  就要用三方程序代理模式进行转发
        StopServer();
    }
    CIOCPAppSrvBase::OnIOCPCaughtError(iIOCPErr, iWSAErr);
}

// IOCP初始化ok   成功也要通知设置
void CAppIOCPSrvImpl::OnIOCPInitializeFinished()
{
    CIOCPAppSrvBase::OnIOCPInitializeFinished();
}
